import RecorderManager from "./index.esm";
import CryptoJS from "crypto-js";

var appId = "2a072be1";
var appSecret = "YWJiOTkwZjU4YmEzYjg3MDE1Zjc2MTg0";
var apiKey = "e9ce17a66ef4dbc314b3106aee97acd8";

var iatWS;
var resultText = "";
var resultTextTemp = "";
var countdownInterval;
var recorder;

/**
 * 
 * @param {*} btnDom 对应语音输入按钮的对象
 * @param {*} inputObject 对应语音输入的结果
 */
const initTalk = (btnDom, inputObject) => {
  let btnStatus = "UNDEFINED"; // "UNDEFINED" "CONNECTING" "OPEN" "CLOSING" "CLOSED"

  const btnControl = btnDom;

  //与麦克风建立通信
  recorder = new RecorderManager("/iflytektalk/");
  //监听麦克风打开时的事件
  recorder.onStart = () => {
    changeBtnStatus("OPEN");
  };
  //监听麦克风语音输入时的事件
  recorder.onFrameRecorded = ({ isLastFrame, frameBuffer }) => {
    if (iatWS.readyState === iatWS.OPEN) {
      iatWS.send(
        JSON.stringify({
          data: {
            status: isLastFrame ? 2 : 1,
            format: "audio/L16;rate=16000",
            encoding: "raw",
            audio: toBase64(frameBuffer),
          },
        })
      );
      if (isLastFrame) {
        changeBtnStatus("CLOSING");
      }
    }
  };
  //监听麦克风关闭时的事件
  recorder.onStop = () => {
    clearInterval(countdownInterval);
  };

  //给语音输入按钮添加点击事件
  btnControl.addEventListener("click", function () {
    if (btnStatus === "UNDEFINED" || btnStatus === "CLOSED") {
      connectWebSocket();
    } else if (btnStatus === "CONNECTING" || btnStatus === "OPEN") {
      // 结束录音
      recorder.stop();
    }
  });

  //打开websocket
  function connectWebSocket() {
    const websocketUrl = getWebSocketUrl();
    if ("WebSocket" in window) {
      iatWS = new WebSocket(websocketUrl);
    } else if ("MozWebSocket" in window) {
      iatWS = new MozWebSocket(websocketUrl);
    } else {
      alert("浏览器不支持WebSocket");
      return;
    }
    changeBtnStatus("CONNECTING");
    iatWS.onopen = (e) => {
      // 开始录音
      recorder.start({
        sampleRate: 16000,
        frameSize: 1280,
      });
      var params = {
        common: {
          app_id: appId,
        },
        business: {
          language: "zh_cn",
          domain: "iat",
          accent: "mandarin",
          vad_eos: 5000,
          dwa: "wpgs",
        },
        data: {
          status: 0,
          format: "audio/L16;rate=16000",
          encoding: "raw",
        },
      };
      iatWS.send(JSON.stringify(params));
    };
    iatWS.onmessage = (e) => {
      renderResult(e.data);
    };
    iatWS.onerror = (e) => {
      console.error(e);
      recorder.stop();
      changeBtnStatus("CLOSED");
    };
    iatWS.onclose = (e) => {
      recorder.stop();
      changeBtnStatus("CLOSED");
    };
  }

  

  

    /**
   * 获取websocket url
   * 该接口需要后端提供，这里为了方便前端处理
   */
    function getWebSocketUrl() {
      // 请求地址根据语种不同变化
      var url = "wss://iat-api.xfyun.cn/v2/iat";
      var version = "v2";
      var host = location.host;
      var date = new Date().toGMTString();
      var get = `GET /${version}/iat HTTP/1.1`;
      var tmp = `host: ${host}\ndate: ${date}\n${get}`;
      //hmac-sha256算法加密
      var tmp_sha256 = CryptoJS.HmacSHA256(tmp, appSecret);
      //base64编码
      var sign = CryptoJS.enc.Base64.stringify(tmp_sha256);
      //对生成授权原始字符串进行拼接
      var authorization_tmp = `api_key="${apiKey}", algorithm="hmac-sha256", headers="host date request-line", signature="${sign}"`;
      //对授权原始字符进行base编码
      var authorization = btoa(authorization_tmp);
      //最终url
      url = `${url}?authorization=${authorization}&date=${date}&host=${host}`;
      return url;
    }
  
    //把语言输入的二进制文件转化为base64(音频)
    function toBase64(buffer) {
      var binary = "";
      var bytes = new Uint8Array(buffer);
      var len = bytes.byteLength;
      for (var i = 0; i < len; i++) {
        binary += String.fromCharCode(bytes[i]);
      }
      return window.btoa(binary);
    }
  
    //录音倒计时
    function countdown() {
      let seconds = 60;
      btnControl.innerText = `录音中（${seconds}s）`;
      countdownInterval = setInterval(() => {
        seconds = seconds - 1;
        if (seconds <= 0) {
          clearInterval(countdownInterval);
          recorder.stop();
        } else {
          btnControl.innerText = `录音中（${seconds}s）`;
        }
      }, 1000);
    }
  
    //修改按钮显示的文本，以及输入框重置功能
    function changeBtnStatus(status) {
      btnStatus = status;
      if (status === "CONNECTING") {
        btnControl.innerText = "建立连接中";
        inputObject.msg = "";
        resultText = "";
        resultTextTemp = "";
      } else if (status === "OPEN") {
        countdown();
      } else if (status === "CLOSING") {
        btnControl.innerText = "关闭连接中";
      } else if (status === "CLOSED") {
        btnControl.innerText = "开始录音";
      }
    }
  
    //处理语言识别的结果
    function renderResult(resultData) {
      // 识别结束
      let jsonData = JSON.parse(resultData);
      if (jsonData.data && jsonData.data.result) {
        let data = jsonData.data.result;
        let str = "";
        let ws = data.ws;
        for (let i = 0; i < ws.length; i++) {
          str = str + ws[i].cw[0].w;
        }
        // 开启wpgs会有此字段(前提：在控制台开通动态修正功能)
        // 取值为 "apd"时表示该片结果是追加到前面的最终结果；取值为"rpl" 时表示替换前面的部分结果，替换范围为rg字段
        if (data.pgs) {
          if (data.pgs === "apd") {
            // 将resultTextTemp同步给resultText
            resultText = resultTextTemp;
          }
          // 将结果存储在resultTextTemp中
          resultTextTemp = resultText + str;
        } else {
          resultText = resultText + str;
        }
      //   console.log(resultTextTemp || resultText || "");
        inputObject.msg = resultTextTemp || resultText || "";
      }
      if (jsonData.code === 0 && jsonData.data.status === 2) {
        iatWS.close();
      }
      if (jsonData.code !== 0) {
        iatWS.close();
        console.error(jsonData);
      }
    }
};

export default initTalk;
